#include <iostream>
#include <thread>
#include "Target.h"

using namespace SystemTool;

// Construct the obj
Target::Target()
{
    m_pLock = new std::mutex;
    m_pObserverContainer = new std::vector<IObserver *>;
}

// Destruct the obj
Target::~Target()
{
    if(m_pObserverContainer)
    {
        m_pObserverContainer->clear();
        delete m_pObserverContainer;
        m_pObserverContainer = nullptr;
    }

    if (m_pLock)
    {
        delete m_pLock;
        m_pLock = nullptr;
    }
}

// Add observer(Target do it)
void Target::Add(IObserver *pObserver)
{
    std::lock_guard<std::mutex> Locker(*m_pLock);
    if(m_pObserverContainer == nullptr)
    {
        return;
    }

    if(m_pObserverContainer->empty())
    {
        m_pObserverContainer->push_back(pObserver);
        return;
    }

    auto Iter = std::find_if(m_pObserverContainer->begin(),m_pObserverContainer->end(),[&pObserver](IObserver * pItem){
        if(pItem == pObserver)
        {
            return true;
        }
        return false;
    });

    if(Iter != m_pObserverContainer->end())
    {
        m_pObserverContainer->erase(Iter);
    }

    m_pObserverContainer->push_back(pObserver);
}

// Remove the observer(Target do it)
void Target::Remove(IObserver *pObserver)
{
    std::lock_guard<std::mutex> Locker(*m_pLock);
    if(m_pObserverContainer == nullptr)
    {
        return;
    }

    if(m_pObserverContainer->empty())
    {
        return;
    }

    auto Iter = std::find_if(m_pObserverContainer->begin(),m_pObserverContainer->end(),[&pObserver](IObserver * pItem){
        if(pItem == pObserver)
        {
            return true;
        }
        return false;
    });

    if(Iter != m_pObserverContainer->end())
    {
        m_pObserverContainer->erase(Iter);
    }
}

// Post Target(Target do it)
void Target::Post(NotifyArgs &Args)
{
    std::lock_guard<std::mutex> Locker(*m_pLock);

    if(m_pObserverContainer == nullptr)
    {
        return;
    }

    std::vector<IObserver *>::iterator Iter = m_pObserverContainer->begin();
    for (Iter = m_pObserverContainer->begin(); Iter != m_pObserverContainer->end(); ++Iter)
    {
        std::thread t = std::thread([&Iter,&Args](){
            (*Iter)->Recv(Args);
        });
        t.detach();
    }
}
